#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include "mytbf.h"

typedef void (*sighandler_t)(int);

static PMYTBF g_atMytbfArray[MYTBF_MAX];
static int g_icounts = 0;
static int pos =0 ;
static int initflag = 0;
static sighandler_t alrm_handler_save ;

static void alrm_handler (int s)
{
    int i ;
    for(i=0 ; i<MYTBF_MAX ; i++)
    {
        if(g_atMytbfArray[i] != NULL)
        {
            g_atMytbfArray[i]->token +=g_atMytbfArray[i]->cps;
            if(g_atMytbfArray[i]->token > g_atMytbfArray[i]->burst)
                g_atMytbfArray[i]->token = g_atMytbfArray[i]->burst;
        }
    }
    alarm(1);

}


static int get_free_pos(void)
{
    int i;
    for(i=0 ; i<=MYTBF_MAX ; i++)
    {
        if(g_atMytbfArray[i]==NULL)
            return i ;
    }
    return -1;
}

static void modle_unload (void)
{
    int i;
    signal(SIGALRM ,alrm_handler_save);
    alarm(0);
    
    for(i=0 ; i<MYTBF_MAX ; i++)
        free(g_atMytbfArray[i]);
}

static void modle_load (void)
{
    alrm_handler_save = signal(SIGALRM , alrm_handler);
    alarm(1);

    atexit(modle_unload);// 钩子函数，程序失败时被调用
}



PMYTBF Mytbf_Init(int cps , int burst)
{
    pos = get_free_pos();
    if(pos < 0)
    {
        return NULL;
    }
    if(!initflag)
    {
        modle_load();
        initflag = 1;
    }
    PMYTBF PTMytbf = (PMYTBF)malloc(sizeof(MYTBF));
    if(PTMytbf == NULL)
        return NULL;
    
    PTMytbf->cps = cps ;
    PTMytbf->burst = burst ;
    PTMytbf->token = 0 ;
    PTMytbf->pos = pos ;
    g_atMytbfArray[pos] = PTMytbf;
    //g_icounts++;
    //return &g_atMytbfArray[g_icounts];
    return PTMytbf;
}




int Mytbf_Destory (PMYTBF ptMytbf)
{
    PMYTBF me = ptMytbf;
    g_atMytbfArray[me->pos] = NULL;
    free(ptMytbf);
    return 0;
}

static int min (int a, int b)
{
    if(a<b)
        return a;
    else    
        return b;
}


int Mytbf_GetToken (int size , PMYTBF ptMytbf)
{
    int n ;
    if(size <= 0)
    {
        return -EINVAL;
    }
    PMYTBF me = ptMytbf;

    while(me->token <= 0)
        pause();
    
    n = min(me->token , size);// 消耗了多少个token

    me->token -= n; // 剩下的token

    return n; // 返回消耗的值，读取相应次数
}

int Mytbf_ReturnToken (int size , PMYTBF ptMytbf)
{
    int n ;
    if(size <= 0)
    {
        return -EINVAL;
    }
    PMYTBF me = ptMytbf;
    me->token += n; 
    if(me->token > me->burst)
        me->token = me->burst;

    return size;
}